'use strict';

const { Service } = require('egg');
const dayjs = require("dayjs");
const isBetween = require('dayjs/plugin/isBetween')
dayjs.extend(isBetween)
const {Op} = require("sequelize");
const ModelName = 'RabbitRoom'
// 增强版本：支持不同格式返回和平滑渐变
function getColorByValueEnhanced(value, options = {}) {
    const {
        format = 'hex', // 'hex' | 'rgb' | 'rgba'
        alpha = 1,      // 透明度
        smooth = true   // 是否使用平滑渐变
    } = options;

    // 确保值在0-1之间
    const safeValue = Math.max(0, Math.min(1, value));

    // 如果使用平滑渐变，使用正弦函数使过渡更自然
    const gradientValue = smooth ?
        (1 - Math.cos(safeValue * Math.PI)) / 2 :
        safeValue;

    // 计算RGB值
    const red = Math.round(255 * (1 - gradientValue));
    const blue = Math.round(255 * gradientValue);

    // 根据指定格式返回颜色值
    switch (format) {
        case 'rgb':
            return `rgb(${red}, 0, ${blue})`;
        case 'rgba':
            return `rgba(${red}, 0, ${blue}, ${alpha})`;
        case 'hex':
        default:
            const hexRed = red.toString(16).padStart(2, '0');
            const hexBlue = blue.toString(16).padStart(2, '0');
            return `#${hexRed}00${hexBlue}`;
    }
}
function filterDataByTimeRange(dataArray, startTime, endTime) {
    // 确保数组按时间排序
    const sortedData = dataArray.sort((a, b) => new Date(a.date) - new Date(b.date));

    // 转换开始和结束时间为Date对象
    const startDate = new Date(startTime);
    const endDate = new Date(endTime);

    // 计算时间差（天数）
    const daysDiff = (endDate - startDate) / (1000 * 60 * 60 * 24);

    // 根据时间差确定时间间隔（分钟）
    let intervalMinutes;
    if (daysDiff <= 1) {
        intervalMinutes = 30; // 半小时
    } else if (daysDiff <= 3) {
        intervalMinutes = 60; // 一小时
    } else {
        intervalMinutes = 120; // 两小时
    }
    // 创建Map存储符合间隔的数据
    const timeMap = new Map();

    // 遍历时间范围内的所有可能时间点
    let currentTime = new Date(startDate);
    while (currentTime <= endDate) {
        const timeKey = currentTime.toISOString();

        // 找到最接近这个时间点的数据
        const closestData = findClosestData(sortedData, currentTime, 5); // 5秒容差

        if (closestData) {
            timeMap.set(timeKey, closestData);
        }

        // 增加相应的时间间隔
        currentTime = new Date(currentTime.getTime() + intervalMinutes * 60 * 1000);
    }

    return Array.from(timeMap.values())
        .sort((a, b) => new Date(a.date) - new Date(b.date));
}

// 辅助函数：找到最接近目标时间的数据
function findClosestData(dataArray, targetTime, toleranceSeconds = 5) {
    const targetTimestamp = targetTime.getTime();

    return dataArray.reduce((closest, current) => {
        const currentDate = new Date(current.date);
        const currentDiff = Math.abs(currentDate.getTime() - targetTimestamp);

        // 只考虑在容差范围内的数据
        if (currentDiff <= toleranceSeconds * 1000) {
            if (!closest) return current;

            const closestDiff = Math.abs(new Date(closest.date).getTime() - targetTimestamp);
            return currentDiff < closestDiff ? current : closest;
        }

        return closest;
    }, null);
}
class RouterService extends Service {
    // 所有列表
    async allList(where) {
        return this.ctx.model[ModelName].findAll({
            where,
            order:[
            ],
        });
    }
    async sync() {
      // 根据autoCollect、collect、report、rabbitVideoRecords表中出现的room进行同步room表
      // 统计四张表中的room字段，保证不重复，并且四张表中有farm_id，使用farmid做区分
      // 1. 查询autoCollect、collect、report、rabbitVideoRecords表中的room字段
      // 2. 查询room表中的room字段
      // 3. 对比两者的差异，如果有新增的room字段，则插入room表
      // 4. 返回新增的room字段
      const { ctx } = this;
      const { model } = ctx;
      const farmId = ctx.query.farmId;
      if (!farmId) throw new Error('farmId不能为空');
      // 1. 查询autoCollect、collect、report、rabbitVideoRecords表中的room字段
      const autoCollect = await model.RabbitAutoCollect.findAll({
        where: {
          // farm_id: farmId,
        },
        attributes: ['room'],
        raw: true,
      });
      const collect = await model.RabbitCollect.findAll({
        where: {
          // farm_id: farmId,
        },
        attributes: ['room'],
        raw: true,
      });
      const report = await model.RabbitReport.findAll({
        where: {
          // farm_id: farmId,
        },
        attributes: ['room'],
        raw: true,
      });
      const rabbitVideoRecords = await model.RabbitVideoRecords.findAll({
        where: {
          // farm_id: farmId,
        },
        attributes: ['room'],
        raw: true,
      });
      // 2. 查询room表中的room字段
      const room = await model.Room.findAll({
        where: {
          // farm_id: farmId,
        },
        attributes: ['room'],
        raw: true,
      });
      // 3. 对比两者的差异，如果有新增的room字段，则插入room表
      const autoCollectRoom = autoCollect.map(item => item.room);
      const collectRoom = collect.map(item => item.room);
      const reportRoom = report.map(item => item.room);
      const rabbitVideoRecordsRoom = rabbitVideoRecords.map(item => item.room);
      const roomRoom = room.map(item => item.room);
      const allRoom = [...autoCollectRoom, ...collectRoom, ...reportRoom, ...rabbitVideoRecordsRoom];
      let newRoom = allRoom.filter(item => !roomRoom.includes(item));
      // 去重
      newRoom = Array.from(new Set(newRoom));
      // 查询字典表的名称映射
      const dict = await model.Dict.findAll();
      const dictMap = {};
      dict.forEach(item => {
        dictMap[item.id] = item.name;
      });
      const insertData = newRoom.map(item => ({
        room: item,
        farm_id: farmId,
        room_text: dictMap[item] || item,
      }));

      for (let i = 0; i < insertData.length; i++) {
        await this.create(insertData[i]);
      }
      return insertData;
    }

    /**
     * 舍外热环境数据
     * @param where
     * @param codeList 查询的采集值编码集合
     * @param startTime
     * @param endTime
     * @returns {Promise<{}>}
     */
    async staticData(where, codeList, startTime, endTime) {
      if (!where.room) {
        throw new Error('room不能为空');
      }
      const { ctx } = this;
      const { model } = ctx;
      // 自动采集的数据
      const autoCollect = await model.RabbitAutoCollect.findAll({
        where,
        attributes: ['date', 'monitor_value', 'monitor_key'],
        raw: true
      });
      // 手动采集的数据
      const collect = await model.RabbitCollect.findAll({
        where,
        attributes: ['date', 'monitor_value', 'monitor_key'],
        raw: true
      });
      // 查询字典
      const dictList = await model.Dict.findAll({
            where: {
                id: {
                    [Op.in]: codeList
                }
            },
            raw: true
        })
      let map = {}
      codeList.forEach(code => {
        let tempData = [
            ...autoCollect.filter(item => item.monitor_key === code),
            ...collect.filter(item => item.monitor_key === code),
        ].map(item => {
          return {
            date: item.date,
            value: item.monitor_value
          }
        })
        const filteredData = filterDataByTimeRange(tempData, startTime, endTime)
        // 计算最大最小值
        let min = Math.min(...filteredData.map(item => item.value))
        let max = Math.max(...filteredData.map(item => item.value))

        // 保证min max有15%的边界，这样让图形存在于中间段数据
        min = Math.abs(min) > 10 ? min.toFixed(0) : min.toFixed(1)
        max = Math.abs(max) > 10 ? max.toFixed(0) : max.toFixed(1)
        let findCode = dictList.find(item => item.id === code)
          // 计算时间差（天数）
          const daysDiff = (startTime - endTime) / (1000 * 60 * 60 * 24);

          // 根据时间差确定时间间隔（分钟）
          let unit = 'YYYY-MM-DD HH:mm:ss';
          if (daysDiff <= 1) {
              unit = 'HH:mm:ss'
          } else if (daysDiff <= 3) {
                unit = 'MM-DD HH:mm'
          } else {
                unit = 'MM-DD HH:mm'
          }
        map[code] = {
          name: findCode ? findCode.name : '',
          min,
          max,
          data: filteredData.map(item => {
              return {
                  name: dayjs(item.date).format(unit),
                  value: item.value
              }
          })
        }
      })
      return map
    }
    /**
     *
     * 2. 202体重、201采食量，按只统计，两只为一笼，最终需要以笼为单位的平均值，近一周数据
     * 4. 料重比，是按笼统计取平均值
     */
    async bodyWeight(data) {
        const { ctx } = this;
        const { model } = ctx;
        const { roomId, startTime, endTime } = data;
        if (!roomId) throw new Error('roomId不能为空');
        if (!startTime) throw new Error('startTime不能为空');
        if (!endTime) throw new Error('endTime不能为空');
        // 1. collect表中的room字段
        const dataList = await model.RabbitCollect.findAll({
            where: {
                room: roomId,
                monitor_key: {
                    [Op.in]: [201, 202, 204]
                },
                date: {
                    [Op.between]: [startTime, endTime]
                }
            },
            attributes: ['date', 'monitor_value', 'monitor_key'],
            raw: true
        });
        const feedList = dataList.filter(item => item.monitor_key === 201);
        const weightList = dataList.filter(item => item.monitor_key === 202)
        // 2. 计算采食量、体重的平均数据；数据维度为每天一条，且一个笼存在两条数据，则数据总数/2=笼数，平均值为笼平均值
        /**
         * 采食量，该数据记录格式为：
         * 每天，每个room，每个笼位
         * 需要计算该room的每个笼位的平均值
         * 1. 采食量，体重，按笼位统计，取平均值
         */
        // 首先获取日期 去重复
        const feedDateList = Array.from(new Set(feedList.map(item => item.date)));
        const weightDateList = Array.from(new Set(weightList.map(item => item.date)));
        /**
         * 计算采食量平均值，按笼为单位
         * 采食量以笼为单位存储
         */
        // 计算每天的所有笼位的和平均值
        let feedDateMap = {}
        feedDateList.forEach(date => {
            if (!feedDateMap[date]) {
                feedDateMap[date] = []
            }
            feedList.forEach(item => {
                if (item.date === date) {
                    feedDateMap[date].push(item.monitor_value)
                }
            })
        })
        // 计算他们的平均值
        let feedResult = []
        for (const feedMapKey in feedDateMap) {
            let total = feedDateMap[feedMapKey].reduce((pre, cur) => {
                return pre + cur
            },0)
            let avg = total / feedDateMap[feedMapKey].length / 2
            feedResult.push({
                date: dayjs(feedMapKey).format('YYYY-MM-DD'),
                value: avg.toFixed(2)
            })
        }
        // 计算最小、最大值
        let feedMin = Math.min(...feedResult.map(item => item.value))
        let feedMax = Math.max(...feedResult.map(item => item.value))
        // 最小、最大浮动15%
        let feedDiff = feedMax - feedMin
        feedMin = feedMin - feedDiff * 0.15
        feedMax = feedMax + feedDiff * 0.15
        feedMin = feedMin.toFixed(0)
        feedMax = feedMax.toFixed(0)
        /**
         * 计算体重，体重按只为单位存储，一笼两只，所以总数需要/2得出笼数据
         */
        let weightDateMap = {}
        weightDateList.forEach(date => {
            if (!weightDateMap[date]) {
                weightDateMap[date] = []
            }
            weightList.forEach(item => {
                if (item.date === date) {
                    weightDateMap[date].push(item.monitor_value)
                }
            })
        })
        let weightResult = []
        for (const weightMapKey in weightDateMap) {
            let avg = weightDateMap[weightMapKey].reduce((pre, cur) => {
                return pre + cur
            },0) / (weightDateMap[weightMapKey].length) // 一笼两只
            weightResult.push({
                date: dayjs(weightMapKey).format('YYYY-MM-DD'),
                value: avg.toFixed(0)
            })
        }
        // 计算最小、最大值
        let weightMin = Math.min(...weightResult.map(item => item.value))
        let weightMax = Math.max(...weightResult.map(item => item.value))
        // 最小、最大浮动15%
        let weightDiff = weightMax - weightMin
        weightMin = weightMin - weightDiff * 0.15
        weightMax = weightMax + weightDiff * 0.15
        weightMin = weightMin.toFixed(0)
        weightMax = weightMax.toFixed(0)

        /**
         * 计算料重比例
         * 那我就比如说计算第1周的第5003笼的料重比也就是8/1-8/8
         * 那就是：
         * 5003笼的周采食量就是：8/1-8/7 的5003笼的采食量在这7天的和
         * 5003笼周增重就是：8/8的5003笼体重-8/1的5003笼体重
         * 每笼的周料重比=每笼周采食量/每笼周增重就是
         * 1号 2 3 4 5 6 7 8
         *
         * @新计算逻辑
         * 每日重量之差/每日采食之差，当天-上一天
         *
         */
        // 基于weightResult、feedResult计算料重比
        let rateList = []
        for (let i = 0; i < weightResult.length -1; i++) {
            let rate = feedResult[i].value / (weightResult[i + 1].value - weightResult[i].value)
            rateList.push({
                date: weightResult[i].date,
                // 小于0取0
                value: ((rate < 0 ? 0 : rate)).toFixed(2)
            })
        }
        // 计算最小、最大值
        let rateMin = Math.min(...rateList.map(item => item.value))
        let rateMax = Math.max(...rateList.map(item => item.value))
        rateMin = rateMin.toFixed(0)
        rateMax = Math.ceil(rateMax).toFixed(0)

      let result = {
        201: {
          name: '日采食量(g/只)',
          data: feedResult.map(item => {
              return {
                  ...item,
                  name: item.date
              }
          }),
          min: feedMin,
          max: feedMax
        },
        202: {
          name: '日体重(g/只)',
          data: weightResult.map(item => {
              return {
                  ...item,
                  name: item.date
              }
          }),
          min: weightMin,
          max: weightMax
        },
        203: {
          name: '日料重比(%/只)',
          data: rateList.map(item => {
              return {
                  date: item.date,
                  name: dayjs(item.date).format('YYYY-MM-DD'),
                  value: item.value
              }
          }),
          min: rateMin,
          max: rateMax
        }
      }
      return result
    }

    async unhealthy(data) {
        const { ctx } = this;
        const { model } = ctx;
        const { roomId, startTime, endTime } = data;
        if (!roomId) throw new Error('roomId不能为空');
        if (!startTime) throw new Error('startTime不能为空');
        if (!endTime) throw new Error('endTime不能为空')
        let dictList = await model.Dict.findAll({
            raw: true
        })
        // 非健康数据 204
        let dataList = await model.RabbitCollect.findAll({
            where: {
                room: roomId,
                monitor_key: 204,
                date: {
                    [Op.between]: [startTime, endTime]
                }
            },
            attributes: ['date', 'monitor_value', 'monitor_key', 'room'],
            raw: true
        });
        dataList = dataList.map(item => {
            return {
                ...item,
                date: dayjs(item.date).format('YYYY-MM-DD'),
                monitor_value: dictList.find(dict => dict.id === item.monitor_value) ? dictList.find(dict => dict.id === item.monitor_value).name : item.monitor_value,
                room_text: dictList.find(dict => dict.id === item.room) ? dictList.find(dict => dict.id === item.room).name : item.room
            }
        })
        // 按天累加
        let dateMap = {}
        dataList.forEach(item => {
            let date = item.date
            if (!dateMap[date]) {
                dateMap[date] = []
            }
            dateMap[date].push(item.monitor_value)
        })
        let result = []
        for (const dateMapKey in dateMap) {
            result.push({
                name: dateMapKey,
                date: dateMapKey,
                value: dateMap[dateMapKey].length
            })
        }
        // 最大最小
        let min = Math.min(...result.map(item => item.value))
        let max = Math.max(...result.map(item => item.value))
        // 最小、最大浮动15%
        let diff = max - min
        min = min - diff * 0.15
        max = max + diff * 0.15
        min = min.toFixed(0)
        max = max.toFixed(0)
        return {
            name: '非健康(只/日)',
            data: result,
            min,
            max,
            list: dataList
        }
    }

    async temEvaluate(data) {
        const { ctx } = this;
        const { model } = ctx;
        const { roomId, startTime, endTime } = data;
        if (!roomId) throw new Error('roomId不能为空');
        if (!startTime) throw new Error('startTime不能为空');
        if (!endTime) throw new Error('endTime不能为空')
        /**
         * 603 结果采食标准化
         * 604 结果体重标准化
         * 605 结果饲料转化标准化
         * 606 结果体温标准化
         * 上面这4个就是每张子图的彩色虚线呀     颜色 散点
         * 603就是子图1的棕黄虚线 就是采食量归一 607 602
         * 604就是子图2的深棕色虚线 就是体重归一 608 602
         * 605就是子图3的黄色虚线 就是重料比归一 609 602
         * 606就是子图4的鲜红色实线 就是体温归一 610 611
         *
         * 602 结果密闭气温01
         * 611 结果密闭气温02
         * 这两个就是密闭舍气温的值就是那个散点呀
         * 602 结果密闭气温01 这个是前3张子图也就是采食、体重、重料比的气温值
         * 611结果密闭气温02 这个是第4张子图也就是体温对应的气温值
         *
         * 607 结果气温采食C值
         * 608 结果气温体重C值
         * 609 结果气温饲料转化C值
         * 610 结果气温体温C值
         * 这个就是对应着气温散点的颜色呀
         * 每张子图旁边有颜色棒，1是蓝色，0是红色，中间渐变
         * 然后气每张子图的气温散点的颜色就是分别用下面的值和旁边的颜色棒对应上然后呈现的呀
         *
         * 607 结果气温采食C值
         * 608 结果气温体重C值
         * 609 结果气温饲料转化C值
         * 610 结果气温体温C值
         */
        // 查询report表
        let dataList = await model.RabbitReport.findAll({
            where: {
                room: roomId,
                date: {
                    [Op.between]: [startTime, endTime]
                },
                result_key: [602, 603,604,605,606, 607,608, 609,610, 611]
            },
            attributes: ['date', 'result_key', 'result_value'],
            raw: true
        });
        dataList = dataList.map(item => {
            return {
                ...item,
                date: dayjs(item.date).format('YYYY-MM-DD HH:mm')
            }
        })
        // 计算每个类型的最小、最大值
        // 采食
        let feedList = dataList.filter(item => item.result_key === 603)
        let feedMin = Math.min(...feedList.map(item => item.result_value))
        let feedMax = Math.max(...feedList.map(item => item.result_value))
        // 最小、最大浮动15%
        let feedDiff = feedMax - feedMin
        feedMin = feedMin - feedDiff * 0.15
        feedMax = feedMax + feedDiff * 0.15
        feedMin = feedMin.toFixed(2)
        feedMax = feedMax.toFixed(2)
        // 体重
        let weightList = dataList.filter(item => item.result_key === 604)
        let weightMin = Math.min(...weightList.map(item => item.result_value))
        let weightMax = Math.max(...weightList.map(item => item.result_value))
        // 最小、最大浮动15%
        let weightDiff = weightMax - weightMin
        weightMin = weightMin - weightDiff * 0.15
        weightMax = weightMax + weightDiff * 0.15
        weightMin = weightMin.toFixed(2)
        weightMax = weightMax.toFixed(2)
        // 重料
        let rateList = dataList.filter(item => item.result_key === 605)
        let rateMin = Math.min(...rateList.map(item => item.result_value))
        let rateMax = Math.max(...rateList.map(item => item.result_value))
        // 最小、最大浮动15%
        let rateDiff = rateMax - rateMin
        rateMin = rateMin - rateDiff * 0.15
        rateMax = rateMax + rateDiff * 0.15
        rateMin = rateMin.toFixed(2)
        rateMax = rateMax.toFixed(2)
        // 体温
        let tempList = dataList.filter(item => item.result_key === 606)
        let tempMin = Math.min(...tempList.map(item => item.result_value))
        let tempMax = Math.max(...tempList.map(item => item.result_value))
        // 最小、最大浮动15%
        let tempDiff = tempMax - tempMin
        tempMin = tempMin - tempDiff * 0.15
        tempMax = tempMax + tempDiff * 0.15
        tempMin = tempMin.toFixed(2)
        tempMax = tempMax.toFixed(2)
        /**
         * 获取颜色分类
         */
        // 607采食颜色
        let feedColorList = dataList.filter(item => item.result_key === 607)
        // 608体重颜色
        let weightColorList = dataList.filter(item => item.result_key === 608)
        // 609重料颜色
        let rateColorList = dataList.filter(item => item.result_key === 609)
        // 610体温颜色
        let tempColorList = dataList.filter(item => item.result_key === 610)
        // 颜色值为1是蓝色，0是红色，中间渐变，根据值的大小动态计算颜色
        let feedColorMap = {}
        feedColorList.forEach(item => {
            feedColorMap[item.date] = item.result_value
        })
        let weightColorMap = {}
        weightColorList.forEach(item => {
            weightColorMap[item.date] = item.result_value
        })
        let rateColorMap = {}
        rateColorList.forEach(item => {
            rateColorMap[item.date] = item.result_value
        })
        let tempColorMap = {}
        tempColorList.forEach(item => {
            tempColorMap[item.date] = item.result_value
        })
        /**
         * 计算散点
         */
        // 602散点
        let scatterList1 = dataList.filter(item => item.result_key === 602)
        // 611散点
        let scatterList2 = dataList.filter(item => item.result_key === 611)
        // 采食散点
        let feedScatterList = scatterList1.map(item => {
            return {
                name: item.date,
                value: item.result_value,
                itemStyle: {
                    color: getColorByValueEnhanced(feedColorMap[item.date], { format: 'rgba' })
                }
            }
        })
        // 体重散点
        let weightScatterList = scatterList1.map(item => {
            return {
                name: item.date,
                value: item.result_value,
                itemStyle: {
                    color: getColorByValueEnhanced(weightColorMap[item.date], { format: 'rgba' })
                }
            }
        })
        // 重料散点
        let rateScatterList = scatterList1.map(item => {
            return {
                name: item.date,
                value: item.result_value,
                itemStyle: {
                    color: getColorByValueEnhanced(rateColorMap[item.date], { format: 'rgba' })
                }
            }
        })
        // 体温散点
        let tempScatterList = scatterList2.map(item => {
            return {
                name: item.date,
                value: item.result_value,
                itemStyle: {
                    color: getColorByValueEnhanced(tempColorMap[item.date], { format: 'rgba' })
                }
            }
        })

        let result = [
            {
                name: '采食量(归一)',
                data: feedList.map(item => {
                    return {
                        name: item.date,
                        value: item.result_value
                    }
                }),
                min: feedMin,
                max: feedMax,
                itemStyle: {
                    color: '#00F0FF'
                },
                scatter: feedScatterList,
                // 散点最小、最大值
                scatterMin: Math.min(...scatterList1.map(item => item.result_value)),
                scatterMax: Math.max(...scatterList1.map(item => item.result_value))
            },
            {
                name: '体重(归一)',
                data: weightList.map(item => {
                    return {
                        value: item.result_value,
                        name: item.date
                    }
                }),
                min: weightMin,
                max: weightMax,

                itemStyle: {
                    color: '#FE860E'
                },
                scatter: weightScatterList,
                // 散点最小、最大值
                scatterMin: Math.min(...scatterList1.map(item => item.result_value)),
                scatterMax: Math.max(...scatterList1.map(item => item.result_value))
            },
            {
                name: '重料比(归一)',
                data: rateList.map(item => {
                    return {
                        value: item.result_value,
                        name: item.date
                    }
                }),
                min: rateMin,
                max: rateMax,
                itemStyle: {
                    color: '#FF5580'
                },
                scatter: rateScatterList,
                // 散点最小、最大值
                scatterMin: Math.min(...scatterList1.map(item => item.result_value)),
                scatterMax: Math.max(...scatterList1.map(item => item.result_value))
            },
            {
                name: '体温(归一)',
                data: tempList.map(item => {
                    return {
                        value: item.result_value,
                        name: item.date
                    }
                }),
                min: tempMin,
                max: tempMax,
                itemStyle: {
                    color: '#3C7FF4'
                },
                scatter: tempScatterList,
                // 散点最小、最大值
                scatterMin: Math.min(...scatterList2.map(item => item.result_value)),
                scatterMax: Math.max(...scatterList2.map(item => item.result_value))
            }
        ]

        return result
    }
    async temThreshold(data) {
      const { ctx } = this;
      const { model } = ctx;
      const { roomId, startTime, endTime } = data;
      if (!roomId) throw new Error('roomId不能为空');
      if (!startTime) throw new Error('startTime不能为空');
      if (!endTime) throw new Error('endTime不能为空')
      // 查询气温 101
      let dataList = await model.RabbitAutoCollect.findAll({
        where: {
          room: roomId,
          monitor_key: 101,
          date: {
            [Op.between]: [startTime, endTime]
          }
        },
        raw: true
      });
      /**
       * 存在多条重复时间的数据，需要将这些数据合并相加monitory_value，并且删除多余的数据
       */
      let dateMap = {}
      dataList.forEach(item => {
        if (dateMap[item.date]) {
          dateMap[item.date].push(item)
        } else {
          dateMap[item.date] = [item]
        }
      })
      let result = []
      for (let key in dateMap) {
        let sum = 0
        let age = ''
        dateMap[key].forEach(item => {
          age = item.age
          sum += Number(item.monitor_value)
        })
        result.push({
          name: dayjs(key).format('YYYY-MM-DD HH:mm:ss'),
          value: (sum / dateMap[key].length).toFixed(2),
          age
        })
      }
      return {
        list: result
      }
    }
    async deviceInfo(data) {
      const { ctx } = this;
      const { model } = ctx;
      const { roomId, endTime } = data;
      if (!roomId) throw new Error('roomId不能为空');
      if (!endTime) throw new Error('endTime不能为空')
      // 查询rabbitVideoRecords中的数据
      let dataList = await model.RabbitVideoRecords.findAll({
        where: {
          room: roomId,
          date: {
            [Op.between]: [dayjs(endTime).format('YYYY-MM-DD') + ' 00:00:00', dayjs(endTime).format('YYYY-MM-DD') + ' 23:59:59']
          }
        },
        raw: true
      });
      // 统计设备总类型 room_out去重
      let deviceTypeList = Array.from(new Set(dataList.map(item => item.room_out)))
      // 查询字典表
      let deviceList = await model.Dict.findAll({
        where: {
          id: {
            [Op.in]: deviceTypeList
          }
        },
        raw: true
      })
      // 统计每个设备最近时间的录像地址url
      deviceList = deviceList.map(item => {
        // 里面有很多条需要根据时间排序最近时间为第一个
        let lastDateData = dataList.filter(data => data.room_out === item.id).sort((a, b) => {
          return new Date(b.date) - new Date(a.date)
        })[0]
        return {
          ...item,
          url:lastDateData ? lastDateData.url :''
        }
      })
      return deviceList
    }
}

module.exports = RouterService;
